<?php
using("Utils_Exceptions_Reflection");
/**
 * Provide a simplified interface for dealing with reflection
 * 
 * <p>This facade provides a reduced set of functions for performing
 * reflective tasks.  Common reflection operations have been 
 * encapsulated in method names which mirror the Reflection API.
 * <p>Use this class to help construct classes and call methods
 * when you only know the names and arguments.
 * <p>This class relies on the IncludeManager to check for and 
 * include classes.
 * 
 * @package junction.utils
 * @author Alexander Schearer <aas11@duke.edu>
 */
class Utils_ReflectionFacade {
	
	/**
	 * Return a new instance of a class
	 * 
	 * <p>Take a class name and create a new instance of it. Note
	 * that this will attempt to load the class if it is not already
	 * present.
	 * 
	 * @throws Utils_ReflectionFacade when an exception occurs or the file
	 * is not found.
	 *
	 * @param String $classname
	 * @param array $args
	 * @return Object a new instance of the class or null
	 */
	public static function getInstance($classname, array $args) {
		try {
			if (!exists($classname))
				throw new Exception("Unable to find class file: " . $classname);
			using($classname);
			$ref = new ReflectionClass($classname);
			if ($ref->getConstructor() == null)
				throw new Exception("Class has no valid constructor");
			if ($ref->getConstructor()->getNumberOfRequiredParameters() != count($args))
				throw new Exception("Wrong number of parameters for constructor");
			return $ref->newInstanceArgs($args);
		} catch (Exception $e) {
			throw new Utils_Exceptions_Reflection($e->getMessage());
		}
	}
	
	/**
	 * Invoke the specified method
	 * 
	 * <p>Invoke the method if it is:
	 * <br>1. Present in the class
	 * <br>2. Public
	 * <br>3. Takes at as many parameters as # args
	 * If the method is successfully called then return its
	 * result, else throw an exception
	 * 
	 * @throw Utils_Exceptions_Reflection when one of the above requirments is not met
	 *
	 * @param Object $class
	 * @param String $method
	 * @param array $args
	 * @return mixed return whatever the method returns
	 */
	public static function invokeArgs($class, $method, array $args) {
		try {
			$ref = new ReflectionObject($class);
			$ref_method = $ref->getMethod($method);
			if ($ref_method->getNumberOfParameters() > count($args))
				throw new Exception("Too few arguments passed");
			return $ref_method->invokeArgs($class, $args);
		} catch (Exception $e) {
			throw new Utils_Exceptions_Reflection($e->getMessage());
		}
	}
}
?>